﻿using HtmlAgilityPack;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;

namespace Ln.Tool.Domain.Managers;

public class NugetCrawlerManager : ITransientDependency
{
	private const string NugetVersionUrl = "https://www.nuget.org/packages/Ln.Abp.Tool#versions-body-tab";

	public NugetCrawlerManager(IDistributedCache<NugetResult> cache)
	{
		//缓存设置1分钟获取一次结果
		this.NugetResult = cache.GetOrAdd("NugetResult", () => { return InitData(); }, () =>
		{
			var options = new DistributedCacheEntryOptions();
			options.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(1);
			return options;
		})!;
	}

	private HtmlDocument HtmlDoc { get; set; }
	private NugetResult NugetResult { get; set; } = new NugetResult();

	private NugetResult InitData()
	{
		NugetResult nugetResult = new NugetResult();
		HtmlWeb web = new HtmlWeb();
		this.HtmlDoc = web.Load(NugetVersionUrl);
		nugetResult.Versions = GetVersionList();
		nugetResult.DownloadNumber = GetDownloadNumber();
		return nugetResult;
	}

	public NugetResult GetNugetResult()
	{
		return this.NugetResult;
	}

	/// <summary>
	/// 获取版本号列表
	/// </summary>
	/// <returns></returns>
	private List<string> GetVersionList()
	{
		List<string> versions = new List<string>();
		var versionDoc = HtmlDoc.DocumentNode.SelectNodes("//*[@id=\"version-history\"]/table/tbody");
		var trDoc = versionDoc.First().ChildNodes.Where(x => x.Name == "tr").ToList();
		foreach (var tr in trDoc)
		{
			var version = tr.ChildNodes.First(x => x.Name == "td").ChildNodes.First(x => x.Name == "a").GetAttributes("title")
				.First().Value;
			versions.Add(version);
		}
		return versions;
	}

	/// <summary>
	/// 获取下载总数
	/// </summary>
	/// <returns></returns>
	private long GetDownloadNumber()
	{
		var spanDoc =
			HtmlDoc.DocumentNode.SelectNodes("//*[@id=\"skippedToContent\"]/section/div/aside/div[1]/div[2]/div[1]/span[2]");
		var downLoadNumber = spanDoc.First().InnerText;
		if (downLoadNumber.Contains("K"))
		{
			downLoadNumber = downLoadNumber.TrimEnd('K');
			return (long)Math.Round(decimal.Parse(downLoadNumber) * 1000);
		}
		return long.Parse(downLoadNumber);
	}
}

public class NugetResult
{
	public long DownloadNumber { get; set; }
	public List<string> Versions { get; set; }
}